'How to get the url segment within a CanActivate guard

I am using a guard to make sure users authenticate before reaching the page they request.

A particular use case foresees that a user enters a url with some query params, such as https://myserver.com/the-page-i-want?par1=val1&par2=val2

Within the guard I need to retrieve both the params and the url segment (i.e. the-page-i-want in this case). In order to do so I have implemented the following piece of code

export class AuthGuard implements CanActivate {

    constructor(private router: Router) {}

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
                   const url = state.url;
                   const queryParams = route.queryParams;
                   // some other logic
    }

}

What I see when I run the code is that the queryParams variable is actually filled with the object containing the parameters passed in the query string. The variable url on the other hand contains the entire url string including the paramenters (i.e. it contains the-page-i-want?par1=val1&par2=val2 in this case).

If I inspect the value of the route parameter I can see that the information I am looking for (i.e. just the-page-i-want) is stored somewhere deep in the _urlSegment property but is not offered via an API.

I am running Angular v2.4.9 with Angular Router 3.4.9

Any suggestion on how to get the url segment would be very much appreciated.



Solution 1:[1]

You should use route.url[0].path instead. According to ActivatedRouteSnapShot documentation, route.url should return an array of UrlSegment, after that you can access the path of your UrlSegment

Solution 2:[2]

One thing I've noticed is that the segments returned by ActivatedRouteSnapshot.url will depend on where in the route heirarchy your canActivate is placed, or at least it did in my situation (not sure if that is due to incorrect router config or intentioanl functionality).

If you place it as the root level route, then you will get an empty array returning as that snapshot is unaware of the routes below it, however if you try to access it from a component, you will get all of the required segments.

I had the same empty array issue as my AuthGuard was at the very top. Not sure how heplful this is, but this worked for me.

In your canActivate, you have both ActivatedRoutESnapshot and RouterStateSnapshot.

The latter contains your full url (after the first /).

I simply took this url and split it.

RouterStateSnapshot.url.split('/') then selected the desired url segment.

Not sure if this is the correct or recommended way.

In my code I was trying to limit specific types of users to specific routes, but also, if the user did not have an auth token, to redirect them to the correct login page based on the route they were trying to access.

My Code is below:

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot)
    : Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {

    return new Promise(async (resolve) => {
      console.log('BOOT AUTH GUARD');

      const token = this.authService.retrieveTokenFromStorage();

      const urlSegments = state.url.split('/');

      if(urlSegments[1] === 'core'){
        ...
      }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Sarun Intaralawan
Solution 2 Robert Lane