Angularにおいて、HTTP通信周りの共通処理を仕込みたいときにInterceptor(インターセプター)という仕組みを使います。
例えば
- HTTP通信のすべてのヘッダーに認証トークンを付与したいとき
- 通信エラー時の処理を共通で設定したい
- 通信ログを残したい
といった使い方ができます。
複数のinterceptorが使えるようですが、それはこちらに例がありますので、今回は単一のinterceptorで実装していきます。
Angular 9.1.4で実証しました。
Interceptorを定義する
まず、適当なディレクトリに共通処理の実装を含むhttp-interceptors.ts
というファイルを作ります。
リクエスト、レスポンスに介入するコードはそれぞれ以下の通りです。
リクエストに介入する
共通のヘッダーを付与したい場合はこちら
http-interceptors.ts
@Injectable()
export class NoopInterceptor implements HttpInterceptor {
constructor(private authService: AuthService) {}
intercept(
req: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
const newReq = req.clone(
{headers: req.headers.set('Authorization', this.authService.authToken)}
);
// cloneされてヘッダーを付与したリクエストを次の処理に引き渡す
return next.handle(newReq);
}
}
レスポンスに介入する
リクエストに介入するのと同じくhttp-interceptors.ts
に記述できます。
ファイルは分けてもいいですし、リクエストの介入と一緒に書いてもいいです。
返り値にpipeすることで介入します。
http-interceptors.ts
import { tap } from 'rxjs/operator';
@Injectable()
export class LoggingInterceptor implements HttpInterceptor {
constructor(private logger: Logger) {}
intercept(
req: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
return next.handle(req).pipe(
// tapオペレータでレスポンスの流れを傍受する
tap(resp => {
// リクエスト成功時のログ出力
console.log(resp);
},
error => {
// エラー時の共通処理やログ出力
console.error(error);
}),
);
}
}
定義したinterceptorをproviderに登録する
定義しただけでは呼び出されないので、app.module.ts
のproviderに定義します。
app.module.ts
@NgModule({
declarations: [
AppComponent,
// AnyComponent
],
imports: [
HttpClientModule,
FormsModule,
AppRoutingModule
],
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: Interceptor, multi: true }
],
bootstrap: [AppComponent],
entryComponents: []
})
export class AppModule { }
これで、同じエラー処理を書かずに済みます。