angular localStorage interceptor

agnusdei·2023년 11월 7일
0
import {
  HttpEvent,
  HttpHandler,
  HttpInterceptor,
  HttpRequest,
} from '@angular/common/http';
import { Injectable, OnDestroy } from '@angular/core';
import { Router } from '@angular/router';
import { Store } from '@ngxs/store';
import { IAdminDTO } from '@namdorang/interface';
import {
  Observable,
  Subscription,
  catchError,
  of,
  switchMap,
  throwError,
} from 'rxjs';
import { AdminStore, SetAdmin } from '../store/auth.store';
import { HttpService } from '../services/http.service';
import { ToastService } from '@common/lib';

@Injectable({
  providedIn: 'root',
})
export class HttpInterceptorImpl implements HttpInterceptor, OnDestroy {
  sub?: Subscription;
  constructor(
    private readonly toastService: ToastService,
    private readonly store: Store,
    private readonly router: Router,
    private readonly httpService: HttpService
  ) {}
  ngOnDestroy(): void {
    this.sub?.unsubscribe;
  }

  intercept(
    req: HttpRequest<any>, // original request
    httpHandler: HttpHandler // handle
  ): Observable<HttpEvent<any>> {
    const accessToken = localStorage.getItem('accessToken');
    // clone : 기존 요청을 복제하여 필요한 요소를 추가하거나 수정하기 위함
    const request = req.clone(
      accessToken
        ? {
            setHeaders: {
              Authorization: `Bearer ${localStorage.getItem('accessToken')}`,
            },
          }
        : {}
    );

    // request 를 처리하는 메소드
    return httpHandler.handle(request).pipe(
      catchError((e) => {
        const status: number = e.status;

        if (status === 498) {
          this.store.reset(AdminStore);

          this.httpService
            .get<{ accessToken: string }>('auth/refresh', {
              headers: {
                RefreshToken: `Bearer ${localStorage.getItem('refreshToken')}`,
              },
            })
            .pipe(
              switchMap(({ accessToken }) => {
                localStorage.setItem('accessToken', accessToken);
                return this.httpService.get<IAdminDTO>('auth');
              }),
              catchError(() => {
                this.toastService.show('로그인 후 이용 가능합니다.', 'primary');
                this.router.navigateByUrl('login');
                return of(null);
              })
            )
            .subscribe((admin) => {
              if (admin) {
                this.store.dispatch(new SetAdmin(admin));
              }
            });
        } else if (status === 401) {
          this.store.reset(AdminStore);
          this.toastService.show(e.error.message, 'danger');
          this.router.navigateByUrl('login');
        } else if (status !== 500) {
          this.toastService.show(e.error.message, 'danger');
        }
        return throwError(() => new Error(e));
      })
    );
  }
}

0개의 댓글