Sankar
Sankar

Reputation: 6532

Angular HttpClient receive and handle 302/307response code; disable redirect

I have the following service for my component:

@Injectable({
  providedIn: 'root',
})
export class MyService {
    constructor(private httpClient: HttpClient ) { }
}
someFunction() {
   this.httpClient.post(url, data, options)
}

I also have a HttpInterceptor like below:

@Injectable({
  providedIn: 'root'
})
export class HttpInterceptorService implements HttpInterceptor {
  constructor() {}

  intercept(
    req: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    return next.handle(req).do(
      (event: HttpEvent<any>) => {
        if (event instanceof HttpResponse) {
          console.log('############### event status: ', event.status);
        }
        console.log('########### event is: ', event);
      },
      (err: any) => {
        if (err instanceof HttpErrorResponse) {
          console.log('HTTP error status is: ', err.status);
        } 
        console.log('error is: ', err);
      }
    );
  }
}

Now, the post call that I have may receieve three types of response codes, either a 200 or a 302 or 307. Now in cases where I get 200 everything works fine. However, when I get 302 or 307, the default HttpClient keeps on following the Location in the response instead of giving me the control. The redirect url is a refresh url but it needs a different type of handling (GET instead of POST and some extra params added).

In case of errors like 400 I correctly get the error in my Interceptor catch block.

Is there a way to disable the HTTP redirect and handle the redirection in my code ?

Upvotes: 2

Views: 13857

Answers (1)

terahertz
terahertz

Reputation: 3491

Taken from Mozilla docs: HTTP response status codes:

HTTP response status codes indicate whether a specific HTTP request has been successfully completed. Responses are grouped in five classes:

Informational responses (100–199),

Successful responses (200–299),

Redirects (300–399),

Client errors (400–499),

and Server errors (500–599).

As you can see, 3xx HTTP status codes are NOT errors but redirects. Only 4xx and 5xx HTTP Status codes are considered as error responses. This is why when your angular app received a 4xx response, your interceptor's catch block correctly handled it.


Taken from Mozilla docs: Redirections in HTTP:

Principle

In HTTP, a redirection is triggered by the server by sending special responses to a request: redirects. HTTP redirects are responses with a status code of 3xx. A browser, when receiving a redirect response, uses the new URL provided and immediately loads it: most of the time, the redirection is transparent to the user, besides a small performance hit.

Unfortunately, when browsers received a 3xx response, they take the initiative and immediately requests for the URI defined in the Location header. Therefore, there isn't a way for you to intercept the response and do something with it.


If the API is your own, it'd be easier for you to simply change it to return a different HTTP status code. You had mentioned the 302 returns a "refresh url". If you are using JWT and you are trying to refresh tokens, then it'd be easier to return a 400: BAD REQUEST or 401: UNAUTHORIZED and let your interceptor's error block handle call the refresh url.

If the API is someone else's, then, consider changing your Angular app design/app flow to handle the redirect response.

Upvotes: 6

Related Questions