Angular HttpClient: How to get raw HTTP response, even if error
Asked Answered
O

3

9

In an Angular service using HttpClient, I've created a method that returns the raw HTTP response from a POST:

httpOptions = {
  headers: new HttpHeaders({
    'Content-Type': 'application/json'
    //observe: 'response'
  }),
  observe: 'response' as 'body'
};

forgotLogin(requestData: PUMRequestData): Observable<HttpResponse<string>> {
  return this.http.post<HttpResponse<string>>("http://...", requestData, this.httpOptions);

Then in my component, I just look at the status and body from the raw http response.

this.api.forgotLogin(pumRequestData).subscribe(response => {
  this.hStatus = response.status;
  this.hBody = response.body;
});

The problem is that if the response status is not in the 200 series, then HttpClient throws an error. In my use case, I just want to get the request status and body regardless of what the status is and I want to decide on what action to take based on the status in my component, not in an error handler in the service. I've been trying to figure some tricky way to create an error handler in the service that simply return the (Observable) HTTP response, and haven't been able to - not even sure if that's the right approach.

So how can I get the raw http response back to my component when the status is not 200 series?

Olga answered 2/10, 2019 at 22:13 Comment(0)
M
5

This worked for me per HttpClient not able to retrieve plain text.

That's right.
It works when there is no generic code applied to it.
it will work for:

http.get(url, {responseType: 'text'}
Madrepore answered 23/1, 2020 at 22:22 Comment(1)
This is the correct answer when the site returns a raw text string!Increase
O
1

Well, I gave in and solved by using an error handler as was suggested (thanks Christopher). What I wanted was an http client that would just pass me back the http response regardless of the status, and only throw an error if no response was returned (e.g. non-existent domain). The Angular HttpClient won't do that. There may be another http client library out there that would, but life's too short.

I only need the HTTP Status and the body from the response, so I created this error handler:

  private handleError(error: HttpErrorResponse) {
    if (error.status == 0)
      return of({ status: 600, body: "Unexpected error. If this problem persists, please contact ..." })
    else
      return of({ status: error.status, body: error.error });
  }

Then my API call methods look like:

  changePassword(requestData: PUMRequestData): Observable<HttpResponse<string>> {
    return this.http.put<any>("http:// ... /API/ChangePassword", requestData, this.httpOptions)
      .pipe(catchError(err => this.handleError(err)));
  }

Now whether the subscriber gets the response from either a successful HTTP Status 200 call or from the error handler, it will contain both 'status' and 'body'. Notice that if there is no HTTP response then I set a fictitious HTTP Status 600, in which case I have to provide the missing error message that would have been in the body. Also I had to change the data type of the put from HttpResponse string to any.

Olga answered 8/10, 2019 at 22:48 Comment(1)
Thank you very much. I've been working on a problem with the Google photos API for days now. The error handler fixed my problem.Lamelliform
U
-1

When you subscribe to the HTTP Response, you may add an error handler. The HttpErrorResponse object includes the HttpHeaders, status, and statusText, which are inherited from HttpResponseBase.

The body is available in the property HttpErrorResponse.error.

HttpResponseBase Properties available on HttpErrorResponse

  • headers: HttpHeaders - All response headers.
  • status: number - Response status code.
  • statusText: string - Textual description of response status code. (Do not depend on this)
  • url: string | null - URL of the resource retrieved, or null if not available.
  • ok: boolean - Whether the status code falls in the 2xx range.

Example

this.api.forgotLogin(pumRequestData).subscribe(
  response => {
    this.hStatus = response.status;
    this.hBody = response.body;
  },
  (error: HttpErrorResponse) => {
    if (error.error instanceof ErrorEvent) {
      // A client-side or network error occurred. Handle it accordingly.
      console.error('An error occurred:', error.error.message);
    } else {
      // The backend returned an unsuccessful response code.
      // The response body may contain clues as to what went wrong,
      console.error(`Backend returned code ${error.status}, ` +
        `body was: ${error.error}`);
    }
  }
);

The error handler may also be placed within an RXJS pipe, so that it can be embedded prior to subscribing to the HTTP request.

this.http.get<Object>(full_url, options).pipe(catchError((error: HttpErrorResponse) => {
  // Process error here, such as logging.
  ...
  return throwError(error)
}))

See Angular HttpClient docs: Error handling

Uxorial answered 3/10, 2019 at 0:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.