How to handle redirect in Angular
Asked Answered
C

5

15

I use spring security, which redirects unauthenticated users to a login page.

So when an unauthenticated angular client sends a GET request to an endpoint (expecting JSON), it receives the HTML content of the login page, and the JSON parser fails (Angular2 watch for 302 redirect when fetching resource)

const httpObservable = this.http.get(urlThatWillRedirect).subscribe(data => ...) // JSON parser will fail

How can I handle redirects in Angular?

Calorie answered 12/9, 2018 at 8:6 Comment(0)
A
11

The correct solution is to change the server side code to not return 302 status codes because browser kicks in the redirect before Angular (or any SPA for that matter) can do anything about it. Usually, you want to return 401/403s for this very purpose.

If this is not possible, the only alternative is to implement a hackish solution to somehow recognize that the response is indeed a redirect and handle it appropriately by using HttpInterceptors. Here's an equivalent example in AngularJS.

In Angular 2+, you could probably follow something like this to check if the response is a redirected page:

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req)
      .do(event => {
        if (event instanceof HttpResponseBase) {
          const response = event as HttpResponseBase;
          if (response && response.ok && response.url && response.url.toLowerCase().indexOf(this.logoPartialUrl) >= 0) {
            // Modify this portion appropriately to match your redirect page
            const queryStringIndex = response.url.indexOf('?');
            const loginUrl = queryStringIndex && queryStringIndex > 0 ? response.url.substring(0, queryStringIndex) : response.url;
            console.log('User logout detected, redirecting to login page: %s', loginUrl);
            window.location.href = loginUrl;
          }
        }
      });
Algorithm answered 12/9, 2018 at 8:32 Comment(0)
B
2

It's not really clean and I would recommend to handle routing and states using Router and Guards. But if JSON parser fails (and this is definition for not logged in you maybe can handle the redirect on client side using the error handler.

const httpObservable = this.http
                                .get(urlThatWillRedirect)
                                .subscribe(
                                  (data) => {//handle data},
                                  (error) => {// redirect to login page}          
                                ); 
Bohn answered 12/9, 2018 at 8:22 Comment(1)
Would be helpful to get an explanation of using Router and Guards.Bombay
E
0

What I have done in similiar scenario is:

  • I have used the option observe: 'response' in order to get full information about the final redirection page url
  • and I have used the url to set as window.location
this.httpClient
    .post("/mydomain/j_spring_security_logout",
          "{}",
          { observe: 'response' ,responseType: 'text'})
    .subscribe(resp =>  {
        console.log(resp);
        if(resp.url != null) {
            window.location.href = resp.url;
        }
      })
Emu answered 5/1 at 14:21 Comment(0)
D
-1

Redirect your page to error in case of any abnormal service response codes. you can handle this by adding a method in service class and add that to catch of Observable of response. Probably we will handle this kind of response for 401 or 403, as @I46kok said try to change error codes as well

   public serviceMethod(){
      this.http.get(urlThatWillRedirect).catch(this.handleError).subscribe(data =>...);
   }


   private handleError(error:any){
       if(error.code === 403|| error.code === 401){
         // clear your user credentials here like localStorage,Auth token etc..
         window.location.href = '/#/error';
         return Observable.throw(error.json());
       }
   }
Defroster answered 12/9, 2018 at 9:15 Comment(2)
Does a 302 response result in an error with HttpClient?Hedgcock
@jrahhali you can find more about this here... developer.mozilla.org/en-US/docs/Web/HTTP/Status/302Defroster
R
-2

Look at angular docs: https://angular.io/guide/http

So what you do:

this.http.get(url, { observe: 'response' }).subscribe(resp => resp.headers.get('location'))

in a location redirect URL is placed

Racemic answered 26/10, 2020 at 21:15 Comment(2)
This shouldn't work, as the browser will intercept 302 and honor it before Angular gets the response. Angular will get the response from the final location, which is what the OP doesn't want.Dogy
@DavidAmmouial Why browser will do a redirect for background XMLHttpRequest? It never does so. I TRIED that code and it WORKS as expectedRacemic

© 2022 - 2024 — McMap. All rights reserved.