Angular HttpClient: как получить необработанный ответ HTTP, даже если ошибка

В службе Angular, использующей HttpClient, я создал метод, который возвращает необработанный HTTP-ответ от 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);

Затем в моем компоненте я просто смотрю на статус и тело из необработанного ответа http.

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

Проблема в том, что если статус ответа не из серии 200, то HttpClient выдает ошибку. В моем случае использования я просто хочу получить статус и тело запроса независимо от того, каков статус, и я хочу решить, какое действие предпринять, основываясь на статусе в моем компоненте, а не в обработчике ошибок в службе. Я пытался придумать какой-то хитрый способ создать обработчик ошибок в службе, который просто возвращает ответ (Observable) HTTP, и не смог - даже не уверен, что это правильный подход.

Итак, как я могу вернуть необработанный http-ответ моему компоненту, если статус не равен 200?


person Chuck Bevitt    schedule 02.10.2019    source источник


Ответы (3)


Это сработало для меня из-за того, что HttpClient не может получить обычный текст.

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

http.get(url, {responseType: 'text'}
person JamesIsSoPro    schedule 23.01.2020
comment
Это правильный ответ, когда сайт возвращает необработанную текстовую строку! - person Display name; 24.04.2021

Ну, я сдался и решил, используя обработчик ошибок, как было предложено (спасибо, Кристофер). Мне нужен был http-клиент, который просто возвращал бы мне ответ http независимо от статуса и выдавал ошибку только в том случае, если ответ не был возвращен (например, несуществующий домен). Angular HttpClient этого не сделает. Там может быть другая клиентская библиотека http, но жизнь слишком коротка.

Мне нужен только статус HTTP и тело ответа, поэтому я создал этот обработчик ошибок:

  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 });
  }

Тогда мои методы вызова API выглядят так:

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

Теперь независимо от того, получает ли подписчик ответ от успешного вызова HTTP Status 200 или от обработчика ошибок, он будет содержать как «статус», так и «тело». Обратите внимание, что если нет ответа HTTP, я устанавливаю фиктивный статус HTTP 600, и в этом случае я должен предоставить отсутствующее сообщение об ошибке, которое было бы в теле. Также мне пришлось изменить тип данных пут из строки HttpResponse на любой.

person Chuck Bevitt    schedule 08.10.2019
comment
Большое тебе спасибо. Я уже несколько дней работаю над проблемой с API Google Photos. Обработчик ошибок исправил мою проблему. - person Greg Harner; 26.03.2020

Подписавшись на ответ HTTP, вы можете добавить обработчик ошибок. Объект HttpErrorResponse включает в себя HttpHeaders, status и statusText, унаследованные от HttpResponseBase.

body доступен в свойстве HttpErrorResponse.error.

HttpResponseBase Недвижимость доступна на HttpErrorResponse

  • заголовки: HttpHeaders — все заголовки ответов.
  • статус: число — код статуса ответа.
  • statusText: строка — текстовое описание кода состояния ответа. (Не зависеть от этого)
  • URL: строка | null — URL извлеченного ресурса или null, если он недоступен.
  • ok: логическое значение — попадает ли код состояния в диапазон 2xx.

Пример

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}`);
    }
  }
);

Обработчик ошибок также может быть помещен в RXJS pipe, чтобы его можно было встроить до подписки на запрос HTTP.

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

См. документацию по Angular HttpClient: Обработка ошибок

person Christopher Peisert    schedule 03.10.2019