[Nest.js] Http module

Woong·2022년 12월 9일
1

Nestjs

목록 보기
10/28
  • Http 모듈을 통해 HTTP 요청을 수행

설치

npm install @nestjs/axios axios

사용하기

  • Module에서 HttpModule 을 import 한다.
@Module({
  imports: [HttpModule],
  providers: [CatsService],
})
export class CatsModule {}
  • axios 옵션 추가
    • 상세 옵션은 여기 참고
@Module({
  imports: [
    HttpModule.register({
      timeout: 5000,
      maxRedirects: 5,
    }),
  ],
  providers: [CatsService],
})
export class CatsModule {}
  • 비동기로 옵션 전달할 수도 있다.
HttpModule.registerAsync({
  imports: [ConfigModule],
  useFactory: async (configService: ConfigService) => ({
    timeout: configService.get('HTTP_TIMEOUT'),
    maxRedirects: configService.get('HTTP_MAX_REDIRECTS'),
  }),
  inject: [ConfigService],
});
  • HttpService 는 Observable 로 래핑된 AxiosResponse 객체를 리턴한다.
@Injectable()
export class CatsService {
  constructor(private readonly httpService: HttpService) {}

  findAll(): Observable<AxiosResponse<Cat[]>> {
    return this.httpService.get('http://localhost:3000/cats');
  }
}

response schema

{
  // 서버로부터 응답받은 데이터
  data: {},

  // HTTP status code
  status: 200,

  // HTTP status message
  statusText: 'OK',

  // 응답받은 HTTP header (lowercase)
  // ex) `response.headers['content-type']`
  headers: {},

  // request 를 위해 axios 에 제공된 config
  config: {},

  // request (리다이렉션시 최종 request, 브라우저는 XMLHttpRequest)
  request: {}
}

파일 다운로드

  • HTTP GET 으로 파일을 다운로드하여 저장하고자 할 경우
const filename: string = downloadUrl.substring(downloadUrl.lastIndexOf('/') + 1)
const response: AxiosResponse<any, any> = await this.httpService.axiosRef({
        url: downloadUrl,
        method: 'GET',
        responseType: 'stream',
      })
const writer = createWriteStream(`${filename}`)
response.data.pipe(writer)
  • Readble 로 callback 으로 넘길 수도 있다.
async downloadFromUrl(downloadUrl: string, callback?) {
  const response: AxiosResponse<any, any> = await this.httpService.axiosRef({
    url: downloadUrl,
    method: 'GET',
    responseType: 'stream',
  })
  
  if (callback) {
    callback(response.data)
  }
}

multipart/form-data 사용하기

  • FormData 를 통해 request body 를 추가한다.
    • Content-Type 는 명시하지 않아도 payload 타입에 기반하여 자동으로 추론된다
    • 파일을 Readable 로 넘겨줄 수 있다.
import * as FormData from 'form-data'
import { Readable } from 'stream'
import { AxiosError, AxiosRequestConfig } from 'axios'
import { catchError, lastValueFrom, map } from 'rxjs'
...
async uploadFile(uploadUrl: string, filestream: Readable): Promise<ResultMetadata> {
  const form: FormData = new FormData()
  form.append('file_type', 'image') // 원하는 body 내용 추가
  form.append('filestream', filestream) // 파일 업로드
  //form.append('filestream', fs.createReadStream('/foo/filename')) // 파일명으로 읽을 경우
  
  const requestConfig: AxiosRequestConfig = {
    headers: { 'Content-Type': 'multipart/form-data' },
    params: {}
  }
  
  return await lastValueFrom(
    this.httpService.post(uploadUrl, form, requestConfig).pipe(
      map(response => response?.data),
      catchError((error: AxiosError) => {
        this.logger.error(`upload file fail : ${error}`)
        throw 'upload file fail'
      }
    )
  )
}

reference

0개의 댓글