web-dev-qa-db-ja.com

特定のサービス専用のインターセプター

アプリには、さまざまなAPI URLを指すいくつかのサービスがあります。次に、これらの各サービスに異なるヘッダーを設定する必要があります。私の質問は、Angular 4.の新しいインターセプターに関するものです。4。特定のサービスに1つのインターセプターを設定する可能性はありますか?それで、各サービスには特定のインターセプターがありますか?

うまくいけば、皆さんは私の質問を受けます。

11
Tom

TL:DR回答:

いいえ、方法はありません。インターセプターはallリクエストをインターセプトするように設計されています。

長い答え:

リポジトリもリクエストも、通過できるインターセプターであることを認識してはなりません。したがって、リクエストにマークを付ける、または特定のクラスをチェックするという解決策には同意しません。

私はむしろここで提供される解決策が好きです: 例Angular HttpInterceptors

基本的に、特定のヘッダーを追加する必要がある場合、インターセプターはサービス(メディエーターパターン)をチェックする必要があります。

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    console.log(JSON.stringify(req));

    const token: string = this.currentUserService.token;

    if (token) {
        req = req.clone({ headers: req.headers.set('Authorization', 'Bearer ' + token) });
    }

    if (!req.headers.has('Content-Type')) {
        req = req.clone({ headers: req.headers.set('Content-Type', 'application/json') });
    }

    req = req.clone({ headers: req.headers.set('Accept', 'application/json') });
    return next.handle(req);
}

これは良い例ですが、単一の責任の原則(複数のヘッダーの設定)に違反していることに注意してください。

それに加えて、私の見解では、インターセプターは問題のパターンが間違っているということです。また、ベアラートークンをリクエストに追加するためのソリューションとしてインターセプターを使用していません。それが私をここに連れてきた私のユースケースでした。

基本的に私はあなたのアーキテクチャに挑戦し、あなたがどのようにリクエストを作成するかを再考します。この問題の解決策は、次の設計です。

Abstract-Repository

HttpRequestを返すget/post/putなどの基本的なメソッドがあります。

パラメータとしてHttpRequestを受け入れる「送信」と呼ばれるメソッドがあります。

Concret-Repository

抽象リポジトリから継承し、基本的なリクエスト機能を拡張します。

したがって、ユースケースでは1つの基本サービスがあり、すべての特定の/カスタムサービスはこの特定のサービスを継承し、リクエストの動作を拡張します。

デコレーター

このアーキテクチャーをさらに一歩進めるために(私がしたように)、すべての装飾された関数の動作を拡張するTypeScriptデコレーターを作成できます(依存関係の注入が必要な場合など、すべての場合で可能ではありません)。たとえば、特定のヘッダーを追加します。これは次のようになります。

import { Observable } from 'rxjs/Observable';
import { HttpClient, HttpRequest, HttpEvent } from '@angular/common/http';
import { Injectable } from '@angular/core';

export abstract class BaseRepository<T> {
    constructor(protected client: HttpClient) {

    }

    public createGetRequest(url: string): HttpRequest<T> {
        return new HttpRequest("GET", url);
    }

    public send(request: HttpRequest<T>): Observable<HttpEvent<T>> {
        return this.client.request(request);
    }
}

@Injectable()
export class NormalServiceRepository extends BaseRepository<any> {

    constructor(protected client: HttpClient) {
        super(client);
    }

    public get(url: string): Observable<any> {
        const baseRequest = super.createGetRequest(url);

        baseRequest.headers.set('Content-Type', 'application/json');

        return this.send(baseRequest);
    }
}



@Injectable()
export class AuthServiceRepository extends BaseRepository<any> {

    constructor(protected client: HttpClient) {
        super(client);
    }

    @AcceptsJson()
    @SendsJson()
    @ForwardCredentials()
    public createGetRequest(url: string): HttpRequest<any> {
        return super.createGetRequest(url);
    }

    public get(url: string): Observable<any> {
        const baseRequest = super.createGetRequest(url);
        return this.send(baseRequest);
    }
}

これで、アーキテクチャがどのように見えるかを示す基本的な図が得られます。

デコレータの詳細

TypeScriptデコレータ

実装例

8
Nightking

新しいHttpClientでリクエスト/レスポンスが発生すると、allインターセプターが呼び出されます。できることの1つは、リクエストをマークすることです。そのため、そのリクエストを処理するように設計されたインターセプターに適切なヘッダーを設定します。

1
Daniel Bunte

この質問には少し遅れますが、これでうまくいきます。はい、インターセプターに入りますが、単純な条件で実行されない場合があります。

 intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // Do not execute interceptor
    if (some condition)
      return next.handle(req);

    // Else.. do your thing and go next...
    // Add headers, modify reqyest, etc..
    return next.handle(req);
  }
0
smorhaim