I started working with Angular a few months ago on a new project but now I need to write a more complicated error interceptor which will detect when the back-end API is down.

The interceptor need to detect the HTTP error code and if the server is down I need to execute a request to a third party API server and get a list of available back-end server URL's, ping each severs from this list until one UP is found and retry the original request(basically to change the base URL).

Here are the steps the that interceptor need to do:

  1. check the error code, if the code is 0 call the method to handle the problem
  2. execute a request to a different API an get a list of all available servers
  3. Iterate through the list and ping each server from that list.
  4. When the available servers is found, retry the original request.

In my case a usual request would be to get a list of projects:

getProjects() {
    return this.http.get<IProject[]>('/projects');
  }

The base URL is missing because I use another interceptor to add it dynamically.

The method that get the list of the avaiblable back-end server URL's:

getRoutes() {
    return this.http.get<IRoute[]>(this.API_URL + '/routes');
  }

and the services that can ping a service

ping(url: string) {
    return this.http.get(url, { observe: 'response', responseType: 'text' });
  }

Until here everything works as expected.

Now the interceptor:

intercept(request, next) {
    return next.handle(request).pipe(
      catchError((error: any) => {
        if (error.status === 0) {
          return this.handleServerDownError(request, next);
        }
        return throwError(error);
      })
    );
  }

handleServerDownError(request, next) {
    return this.routesService.getRoutes().pipe(
      map(routes => {        
         routes.map((route: IRoute) =>
            this.pingService.ping(route.value).subscribe(res => {
              if (res.status === 200) {
                const updatedReq = request.clone({
                  url: route.value + request.url
                });
                return next.handle(updatedReq);
              }
            })
          );
      })
    );
  }

I almost got i working but of course that the ping method returns the same error code if the pinged server is down and I receive the same error code and I enter in an endless loop.

Any ideas to get it working? Maybe I can change that the ping method returns a different code?

Also how can I stop iterating in a map function after the first available server is found?

Thanks in advance!

1 Answers

1
Community On Best Solutions

I almost got i working but of course that the ping method returns the same error code if the pinged server is down and I receive the same error code and I enter in an endless loop.

For this, you can add a dummy path at the end of the ping urls (example: http://something:8080/dummy_ping) so that you can identify if it is a ping request inside your if condition

if (error.status === 0 && !this.isDummyRequest(request)) {
  return this.handleServerDownError(request, next);
}
...
...

private isDummyRequest(request: HttpRequest<any>): boolean {
    if (request.url.includes('/dummy_ping')) {
      return true;
    } else {
      return false;
    }
}

Also how can I stop iterating in a map function after the first available server is found?

Using find function instead of map can be an option