序章

AngularのHttpInterceptorは、発信リクエストまたは着信応答をインターセプトまたはミュートするメカニズムを提供します。 フロントエンドを除いて、Expressのようなフレームワークを備えたミドルウェアの概念と非常によく似ています。 インターセプターは、キャッシングやロギングなどの機能に非常に役立ちます。

注:ここの内容はAngular4.3以降に適用されます。

この記事では、AngularプロジェクトでのHttpInterceptorの使用について学習します。

基本設定

インターセプターを実装するには、注入可能でHttpInterceptorを実装するクラスを作成する必要があります。 クラスは、HttpInterceptorを正しく実装するために、interceptメソッドを定義する必要があります。 インターセプトメソッドは、requestnextの2つの引数を取り、タイプHttpEventのオブザーバブルを返します。

  • requestはリクエストオブジェクト自体であり、タイプはHttpRequestです。
  • nextは、タイプHttpHandlerのHTTPハンドラーです。 ハンドラーにはhandleメソッドがあり、目的のHttpEventオブザーバブルを返します。

以下は、基本的なインターセプターの実装です。 この特定のインターセプターは、RxJS do演算子を使用して、要求のfilterクエリパラメーターの値とHttpEventステータスをコンソールに記録します。 do演算子は、次のような副作用に役立ちます。

インターセプター/my.interceptor.ts
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpHandler, HttpRequest, HttpEvent, HttpResponse }
  from '@angular/common/http';

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/do';
@Injectable()
export class MyInterceptor implements HttpInterceptor {
  intercept(
    req: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
return next.handle(req).do(evt =&gt; {
  if (evt instanceof HttpResponse) {
    console.log('---&gt; status:', evt.status);
    console.log('---&gt; filter:', req.params.get('filter'));
  }
});

インターセプターを接続するには、HTTP_INTERCEPTORSトークンを使用してアプリモジュールまたは機能モジュールでインターセプターを提供しましょう。

app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { MyInterceptor } from './interceptors/my.interceptor';

複数の迎撃機

次のようなもので複数のインターセプターを定義できます。

providers: [
  { provide: HTTP_INTERCEPTORS, useClass: MyInterceptor, multi: true },
  { provide: HTTP_INTERCEPTORS, useClass: MySecondInterceptor, multi: true }
],

インターセプターは、提供された順序で呼び出されます。 したがって、上記の場合、MyInterceptorは最初にHTTPリクエストを処理します。

リクエストの変更

HttpRequestオブジェクトは不変であるため、オブジェクトを変更するには、最初にコピーを作成し、次にコピーを変更して、変更したコピーに対してhandleを呼び出す必要があります。 リクエストオブジェクトのcloneメソッドは、まさにそれを行うのに便利です。 filterクエリパラメータをcompletedの値に設定する単純なインターセプターは次のとおりです。

@Injectable()
export class MyInterceptor implements HttpInterceptor {
  intercept(
    req: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    const duplicate = req.clone({ params: req.params.set('filter', 'completed') });

    return next.handle(duplicate);
  }
}

そして、これがリクエストの本文にあるpizzaという単語のすべての出現をピザ絵文字に変更するインターセプターの最後の例です(🍕)。 本文のないリクエストは、return next.handle(req)を使用して元のリクエストを返すことでパススルーされます。

@Injectable()
export class MyInterceptor implements HttpInterceptor {
  intercept(
    req: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    if (req.body) {
      const duplicate = req.clone({ body: req.body.replace(/pizza/gi, '🍕') });
      return next.handle(duplicate);
    }
    return next.handle(req);
  }
}