AngularのGuardの中で、遷移元のパス (URL) を取得したい

こんばんは。 たーせるです。

ついに@ngrxもバージョン8 になりましたね。

正直、@ngrxはSingleS PageP ApplicationsAにおける状態管理ライブラリとしてはながらくvuexこうじんを拝してきた感がありました。 しかし上記のツイートからも判る通り、今回はなかなかどうして本質的なコーディングに集中できるようAPIが洗練されたなぁと思いました。


閑話休題 今日の記事は、こちらの続きになります。

tercel-tech.hatenablog.com

やりたいこと

Guardの中で、遷移元のパス (URL) に応じて認可の可否を制御したい。 そのために遷移元のパスが何だったのかを調べたい!

もう少しだけ具体的に申しますと、直リンクを禁止したい(必ず特定のページを経由してアクセスさせたい)ような場合に使えるテクニックをご紹介したいと思います。

ソリューション

Angular の RoutesRecognized イベントと、rxjs の pairwise オペレータを使う。

pairwise は、現在の値current value前回の値previous valueを配列としてまとめて出力するオペレータです。

この前回の値previous valueを適当なフィールドに保持しておけば、いざというときどこから来たのかを調べることができます。

import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router, RoutesRecognized } from '@angular/router';
import { Observable } from 'rxjs';
import { filter, pairwise } from 'rxjs/operators';

@Injectable({ providedIn: 'root' })
export class AppGuard implements CanActivate {
  private prevUrl: string;  // 直前のURLがブチ込まれる
  constructor(router: Router) {
    router.events
      .pipe(
        filter(e => e instanceof RoutesRecognized),
        pairwise<RoutesRecognized>())
      .subscribe(x => this.prevUrl = x[0].urlAfterRedirects);
  }

  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
    /* 略 */
  }
}

フィールド prevUrl には、前回の URL が格納されます。 ちなみに初回アクセス時には、undefined が入っています。

制限事項

よそのサイトからアクセスした場合や、F5 (Ctrl + R) で再読み込みした場合、prevUrlundefined になります。

もし、どうしても再読み込みに対応したい場合は、window.performance.navigation が、数値の1 と等しいかどうかを調べることで一応対応できます(ただ、window.performance.navigation非推奨deprecatedAPIなので、少なくとも売り物に組み込むべきではないというのが僕の考えです)。

では、また。

Copyright (c) 2012 @tercel_s, @iTercel, @pi_cro_s.