6

While using Angular HttpClient post, it seems the default is to treat the response as JSON string. This caused error even for 201 response when the response body is empty as empty string "" fails JSON.parse().

The solution is to specify responseType: "text" as additional option, so that empty body is not treated as error.

However, the API endpoint does return error description in JSON when the request fails (i.e. empty on success, JSON on error).

How do you construct the HttpClient post so that I can get the error message object back when it fails and success does not count as error?

e.g.:

.subscribe(() => {
    // do something for success, no return object as the body is empty
  , error => {
    // do something with the returned error object
    // right now success is still counted as an error due to the issue above
  }
);
5
  • Shouldn't the API use 204 for empty response, instead of 200? Commented Aug 8, 2019 at 2:57
  • @RaulSauco Updated for you. Cheers. Commented Aug 8, 2019 at 2:59
  • I think angular is using the response codes to guess the type of the response, if there is a problem, it does not expect 201 or 200 but some other code, like 422 for validation errors or 500 for server error. For an empty response, but no error, it should be 204. Could you try with that? I have a few angular apps that send requests to a few different APIs and I never saw this problem before. Commented Aug 8, 2019 at 3:03
  • @RaulSauco yes 204 works. I guess it happens when you are dealing with some API endpoints that return 200, 201 with empty body instead of {}. But is there a way to workaround them on the client side as I cannot update the API endpoints. Commented Aug 8, 2019 at 3:08
  • Sorry, I am not sure about that, I haven't run into that situation, hopefully someone else will be able to answer. Good luck Commented Aug 8, 2019 at 3:10

1 Answer 1

9

A server that returns response code 200 or 201 with an empty response body and Content-Type specified as application/json is misconfigured, since an empty string is not valid JSON.

As the OP indicated, specifying responseType: "text" fixes the error, since the empty body is not parsed as JSON.

A workaround is to proceed with responseType: "text" and check if the response body is empty. If the response body is not empty, then call JSON.parse(response).

Example

import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse, HttpHeaders, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';


type HttpOptions = {
  headers?: HttpHeaders | { [header: string]: string | string[]; };
  observe?: "body"; params?: HttpParams | { [param: string]: string | string[]; };
  reportProgress?: boolean; responseType?: "json" /* or "text" as "json" */;
  withCredentials?: boolean;
}

let get_http_options_text = (): HttpOptions => {
  return {
    headers: {'Content-Type': 'text/plain'},
    observe: "body",
    responseType: "text" as "json",  // @see https://github.com/angular/angular/issues/18586
    withCredentials: true
  }
}


@Injectable()
export class MyHttpService {

  constructor(private http: HttpClient) {}

  public post_body_as_string(url: string, body: any, http_params: HttpParams = null):
    Observable<any> {

    let options = get_http_options_text();
    if (http_params != null) {
      options['params'] = http_params;
    }

    return this.http.post<string>(url, body, options).pipe(
      map(response => {
        if (response !== '') {
          return JSON.parse(response);
        } else {
          return {}
        }
      })
    );
  }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you! Very well, I was hoping for a solution that uses just config options, but I guess in this case we can't avoid writing custom code to handle that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.