Angular: 인터셉터를 사용하여 아름다운 방식으로 Angular HTTPClient로 여러 API 사용

Angular 애플리케이션에서 헤더가 다른 여러 백엔드를 사용하면 지루하고 지저분해 보일 수 있지만 어떻게 해야 할까요?

필요할 때 항상 환경 파일을 가져오고 참조하는 대신 HttpInterptor를 사용하여 올바른 백엔드 기본 URL을 추가하고 컨텍스트를 기반으로 헤더를 설정합니다. 서버 렌더에서 다른 환경을 처리하는 데 문제가 있는 경우에도 솔루션이 될 수 있습니다.

기본적으로 아이디어는 각 HTTP 요청에서 백엔드 기본 URL을 식별하기 위해 "@api-x"로 URL의 문자열 접두사를 사용하는 것입니다.

this.http.get('@api-x/specific_endpoint')


어떻게 작동합니까? 아래 가이드를 따르십시오.



1- 먼저 HttpInterceptor를 사용하여 인터셉터를 만들어야 합니다.

import { Injectable } from @angular/core’;
import { HttpInterceptor, HttpHandler, HttpRequest, HttpEvent } from @angular/common/http;
import { Observable } from rxjs;
import { environment } from environments/environment;
@Injectable()
export class ApiInterceptor implements HttpInterceptor {
 constructor() { }
 intercept(
   req: HttpRequest<any>,
   next: HttpHandler
 ): Observable<HttpEvent<any>> {
   // Get the request url
   let requestUrl = req.url;
   // if the request URL have the string prefix, 
   // then make the replace by the correct url 
   if (requestUrl.indexOf(@api-x) !== -1) {
     requestUrl = requestUrl.replace(@api-x, environment.api);
   }
   // clone the http request
   req = req.clone({
     url: requestUrl
   });
   // move to next HttpClient request life cycle
   return next.handle(req);
 }
}


여기에서 기본적으로 요청을 수신하고 요청된 URL의 문자열 접두사 "api-x"를 환경 파일에 정의된 올바른 URL로 바꾸는 인터셉터를 만들고 있습니다.

2- 일부 응용 프로그램 모듈에 생성된 인터셉터를 추가합니다. 제공자 배열에 등록합니다.

...
imports: [
 // import the http client module
 HttpClientModule,
 ...
],
providers: [
 // register the interceptor created
 {
   provide: HTTP_INTERCEPTORS,
   useClass: ApiInterceptor,
   multi: true
 },
 
]
...


응용 프로그램에 SharedModule이 있는 경우 AppModule 또는 SharedModule에 등록하는 것이 좋습니다. 그러나 주의할 점은 HttpClientModule을 가져오는 동일한 모듈이나 자식 모듈에 제공해야 합니다. 왜 필요합니까? 이력서에서 의존성 주입이 Angular에서 작동하는 방식 때문입니다.

3- http 클라이언트를 가져오고 요청을 생성합니다.

...
constructor(
  // import the dependency with the constructor
  private http: HttpClient
) {}
getNews() {
  return this.http.get(@api-x/specific_endpoint_to_get_news');
}
...


이제 요청 URL 매개변수에 접두사 @api-x를 사용하기만 하면 어려움 없이 요청할 수 있습니다.
그러나 더 많은 기본 지원 URL이 필요한 경우 무엇을 할 수 있습니까?

4- 접두사를 더 추가합니다.
ApiInterceptor의 구현을 수정합니다.

...
let requestUrl = req.url;
if (requestUrl.indexOf(@api-x) !== -1) {
  requestUrl = requestUrl.replace(@api-x, environment.api);
}
//added: a new prefix "@api-y"
if (requestUrl.indexOf(@api-y) !== -1) {
  requestUrl = requestUrl.replace(@api-y, environment.otherBackEnd);
}
...


새 API에 새 요청을 추가합니다.

...
constructor(
  private http: HttpClient
) {}
getNews() {
  return this.http.get('@api-x/specific_endpoint_to_get_news');
}

getDocuments() {
  return this.http.get('@api-y/specific_endpoint_to_get_documents');
}

...


자, 이제 여러 API를 쉽게 사용할 수 있습니다. 하지만 헤더를 설정해야 하는 경우 어떻게 해야 할까요?
5- 컨텍스트를 기반으로 헤더를 설정합니다.
수락하도록 ApiInterceptor를 수정합니다.

...
// added: capture the token - could be a service call here
const tokenApiX = localStorage.getItem(tokenApiX);
let requestUrl = req.url;
if (requestUrl.indexOf(@api-x) !== -1) {
   requestUrl = requestUrl.replace(@api-x, environment.api);
   // added: add the header 
   // only to request with url that contain the prefix @api-x
   req = req.clone({setHeaders: {
     Content-Type: 'application/json',
     Access-Control-Allow-Origin: '*',
     Authorization: "Bearer " + tokenApiX 
   }});
}
if (requestUrl.indexOf(@api-y) !== -1) {
  requestUrl = requestUrl.replace(@api-y, environment.otherBackEnd);
}
...


각 백엔드 기본 URL에 대한 워크플로를 제어하는 ​​방법에 따라 애플리케이션에 필요한 헤더를 특정 문자열 접두사 또는 둘 모두에 적용할 수 있습니다. 우리는 우리가 원하는 모든 것을 할 수 있습니다. 그것은 강력하다.
좋아요, 하지만 서버 렌더링 컨텍스트에서 어떻게 도움이 될까요?

6- 브라우저 또는 노드(서버)와 같은 런타임 환경에 따라 다른 백엔드 기본 URL을 처리합니다.
인터셉터를 수정합니다.

import { PLATFORM_ID, Inject } from @angular/core’;
import { isPlatformBrowser} from @angular/common’;
…
export class ApiInterceptor implements HttpInterceptor {
 constructor(@Inject(PLATFORM_ID) platformId: string) { }
 intercept(

 if (requestUrl.indexOf(@api-x) !== -1) {
   // added: verification of browser context
   if (isPlatformBrowser(platformId);) {
     //this is only executed on the browser
     requestUrl = requestUrl.replace(@api-x, environment.apiExternal);
   } else {
     //this is only executed on the server
     requestUrl = requestUrl.replace(@api-x, environment.apiInternal);
   }
}



이제 동일한 http 요청 코드로 많은 수정 없이 런타임 컨텍스트에 따라 다른 APIS 주소를 사용할 수 있습니다.
우리는 또한 API 인터셉터 구현 코드를 개선하고 리팩토링을 할 수 있지만 이것은 다른 기사의 대상입니다.

좋은 웹페이지 즐겨찾기